﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Collections.Observable;
using System.Collections.Specialized;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;

namespace ObservableUnitTests
{
    /// <summary>
    /// Summary description for ObservableListTest
    /// </summary>
    [TestClass]
    public class ObservableListTest
    {
        public ObservableListTest()
        {           
        }

        ObservableList<int> ObservableList;
        List<NotifyCollectionChangedEventArgs> ObservableEvents;

        [TestInitialize]
        public void TestInitialize()
        {
            ObservableList = new ObservableList<int> { 1, 2, 3, 4, 5 };
            ObservableEvents = new List<NotifyCollectionChangedEventArgs>();

            ObservableList.CollectionChanged += (s, e) => ObservableEvents.Add(e);
        }

        
        [TestMethod]
        public void BasicSerialization()
        {
            ObservableList<int> deserialized;

            BinaryFormatter formatter = new BinaryFormatter();

            using (TempFile tmpFile = new TempFile())
            {
                FileStream stream = tmpFile.Stream;
                formatter.Serialize(stream, ObservableList);
                stream.Seek(0, SeekOrigin.Begin);
                deserialized = (ObservableList<int>)formatter.Deserialize(stream);            
            }

            Assert.AreEqual(ObservableList.Count, deserialized.Count);
            Assert.IsTrue( Enumerable.SequenceEqual(ObservableList, deserialized) );
        }

        [TestMethod]
        public void PropertyChanged_UnsubscribeAndSubscribeFromRepalce()
        {
            NotifyPropertyChange original = new NotifyPropertyChange("original");
            NotifyPropertyChange replaced = new NotifyPropertyChange("replaced");
            List<NotifyPropertyChange> notifyList = new List<NotifyPropertyChange>();

            ObservableListBase<NotifyPropertyChange, List<NotifyPropertyChange>> observableList =
                   new ObservableListBase<NotifyPropertyChange, List<NotifyPropertyChange>>(notifyList);

            observableList.Add(original);

            List<string> propertyNames = new List<string>();
            observableList.PropertyChanged += (s, e) => propertyNames.Add(e.PropertyName);

            observableList[0] = replaced;

            //run through all items and trigger PropertyChange events for each.
            foreach (NotifyPropertyChange o in observableList)
            {
                o.Notify();
            }

            //verify that exactly one event was fired and that it was for "replaced" item.
            Assert.AreEqual(1, propertyNames.Count);
            Assert.AreEqual(propertyNames[0], replaced.Name);
        }
    }
}
